import scrapy
import time
import json
import re
import hashlib


class TaobaoSpider(scrapy.Spider):
    name = "taobao"

    def start_requests(self):
        """第一步：访问主页面获取token"""
        yield scrapy.Request(
            url='https://uland.taobao.com/sem/tbsearch?refpid=mm_26632258_3504122_32538762&keyword=%E7%94%B5%E8%84%91&clk1=ce7a38f85581c49cbb5e188b77baa4c1',
            callback=self.parse_main_page,
            headers={
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36',
            }
        )

    def parse_main_page(self, response):
        """解析主页面，提取token"""
        print("正在解析主页面获取token...")

        # 方法1: 从script标签中提取token
        token = None
        scripts = response.xpath('//script/text()').getall()

        for script in scripts:
            if '_m_h5_tk' in script:
                # 匹配 _m_h5_tk="token_timestamp" 格式
                match = re.search(r'_m_h5_tk[\s=]*([^\s,;]+)', script)
                if match:
                    token = match.group(1).strip('"\'')
                    print(f"从script中找到token: {token}")
                    break

        # 方法2: 从cookie中获取
        if not token:
            set_cookie_headers = response.headers.getlist('Set-Cookie')
            for cookie_header in set_cookie_headers:
                cookie_str = cookie_header.decode('utf-8')
                if '_m_h5_tk' in cookie_str:
                    match = re.search(r'_m_h5_tk=([^;]+)', cookie_str)
                    if match:
                        token = match.group(1)
                        print(f"从cookie中找到token: {token}")
                        break

        if token:
            # 清理token（移除时间戳部分）
            clean_token = token.split('_')[0] if '_' in token else token
            print(f"使用token: {clean_token}")

            # 使用token调用API
            yield self.make_api_request(clean_token, token)
        else:
            print("未找到token，尝试直接调用API")
            yield self.make_api_request(None, None)

    def make_api_request(self, token, full_token):
        """构建API请求"""
        current_time = str(int(time.time() * 1000))

        # 构建请求数据
        request_data = {
            "appId": "43356",
            "params": {
                "device": "HMA-AL00",
                "isBeta": "false",
                "from": "nt_history",
                "brand": "HUAWEI",
                "info": "wifi",
                "network": "wifi",
                "client_os": "Android",
                "m": "pc_sem",
                "page": "1",
                "n": 12,
                "q": "电脑",
                "tab": "all",
                "pageSize": 12,
                "sort": "_coefp"
            }
        }

        data_str = json.dumps(request_data, separators=(',', ':'))

        # 如果有token，计算签名
        if token:
            sign = self.calculate_sign(token, current_time, data_str)
        else:
            sign = ""

        headers = {
            'accept': 'application/json, text/plain, */*',
            'accept-language': 'zh-CN,zh;q=0.9',
            'content-type': 'application/x-www-form-urlencoded',
            'origin': 'https://uland.taobao.com',
            'referer': 'https://uland.taobao.com/sem/tbsearch',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36',
        }

        # 构建POST数据
        post_data = {
            'jsv': '2.7.2',
            'appKey': '12574478',
            't': current_time,
            'api': 'mtop.relationrecommend.wirelessrecommend.recommend',
            'v': '2.0',
            'type': 'json',
            'dataType': 'json',
            'data': data_str,
        }

        if sign:
            post_data['sign'] = sign

        # 构建cookies
        cookies = {}
        if full_token:
            cookies['_m_h5_tk'] = full_token
            cookies['_m_h5_tk_enc'] = hashlib.md5(full_token.encode()).hexdigest()

        cookies.update({
            'cna': 'yJ+YIWfuNlwCAXsOOqsB+sO9',
            '_tb_token_': 'e535ba53e8d47',
        })

        return scrapy.FormRequest(
            url='https://h5api.m.taobao.com/h5/mtop.relationrecommend.wirelessrecommend.recommend/2.0/',
            formdata=post_data,
            cookies=cookies,
            headers=headers,
            callback=self.parse_api,
            method='POST'
        )

    def calculate_sign(self, token, t, data):
        """计算签名 - 淘宝的签名算法"""
        sign_str = f"{token}&{t}&12574478&{data}"
        return hashlib.md5(sign_str.encode()).hexdigest()

    def parse_api(self, response):
        """解析API响应"""
        print(f"API响应状态: {response.status}")

        try:
            # 尝试解析JSON
            if response.headers.get('Content-Type', b'').decode().startswith('application/json'):
                data = response.json()
            else:
                # 可能是JSONP格式
                text = response.text
                if text.startswith('mtopjsonp') and text.endswith(')'):
                    json_str = text[text.find('(') + 1:-1]
                    data = json.loads(json_str)
                else:
                    data = {'raw_text': text}

            print("API响应数据:")
            print(json.dumps(data, indent=2, ensure_ascii=False))

            # 检查错误信息
            if 'ret' in data:
                for ret_msg in data['ret']:
                    if 'FAIL_SYS_TOKEN' in ret_msg:
                        print("Token错误，需要重新获取token")
                    elif 'SUCCESS' in ret_msg:
                        print("API调用成功!")
                        if 'data' in data:
                            self.process_data(data['data'])
                    else:
                        print(f"API返回: {ret_msg}")

        except Exception as e:
            print(f"解析响应失败: {e}")
            print(f"原始响应: {response.text}")

    def process_data(self, data):
        """处理成功返回的数据"""
        print("成功获取到推荐数据!")
        if data and 'result' in data:
            result = data['result']
            print(f"获取到推荐结果，数据类型: {type(result)}")